/*
 * Tencent is pleased to support the open source community by making Blueking Container Service available.
 * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
 * Licensed under the MIT License (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * http://opensource.org/licenses/MIT
 * Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package types

import "fmt"

const (
	DefaultAdmissionNamespace = "bkbcs"
)

type AdmissionWebhookConfiguration struct {
	TypeMeta   `json:",inline"`
	ObjectMeta `json:"metadata"`
	//resources ref
	ResourcesRef *ResourcesRef `json:"resourcesRef"`
	//adminssion webhook info
	AdmissionWebhooks []*AdmissionWebhook `json:"admissionWebhooks"`
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AdmissionWebhookConfiguration) DeepCopyInto(out *AdmissionWebhookConfiguration) {
	*out = *in
	out.TypeMeta = in.TypeMeta
	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
	if in.ResourcesRef != nil {
		in, out := &in.ResourcesRef, &out.ResourcesRef
		*out = new(ResourcesRef)
		**out = **in
	}
	if in.AdmissionWebhooks != nil {
		in, out := &in.AdmissionWebhooks, &out.AdmissionWebhooks
		*out = make([]*AdmissionWebhook, len(*in))
		for i := range *in {
			if (*in)[i] != nil {
				in, out := &(*in)[i], &(*out)[i]
				*out = new(AdmissionWebhook)
				(*in).DeepCopyInto(*out)
			}
		}
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdmissionWebhookConfigurationSpec.
func (in *AdmissionWebhookConfiguration) DeepCopy() *AdmissionWebhookConfiguration {
	if in == nil {
		return nil
	}
	out := new(AdmissionWebhookConfiguration)
	in.DeepCopyInto(out)
	return out
}

type ResourcesRef struct {
	//admission operation, Http method: POST=Create; PUT=Update
	Operation AdmissionOperation `json:"operation"`
	//resources kind, mesos resources json: Deployment,Application...
	Kind AdmissionResourcesKind `json:"kind"`
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourcesRef) DeepCopyInto(out *ResourcesRef) {
	*out = *in
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AgentSchedInfo.
func (in *ResourcesRef) DeepCopy() *ResourcesRef {
	if in == nil {
		return nil
	}
	out := new(ResourcesRef)
	in.DeepCopyInto(out)
	return out
}

type AdmissionWebhook struct {
	//admission webhook name
	Name string `json:"name"`
	//failurePolicy, if communication with webhook service failed,
	//according to FailurePolicy to decide continue or return fail
	FailurePolicy WebhookFailurePolicyKind `json:"failurePolicy"`
	//webhook http client config
	ClientConfig *WebhookClientConfig `json:"clientConfig"`

	NamespaceSelector *NamespaceSelector `json:"namespaceSelector"`
	//webhook server list, examples: ["https://127.0.0.1:31000","https://127.0.0.1:31001",...]
	WebhookServers []string `json:"-"`
}

type NamespaceSelector struct {
	Operator NamespaceSelectorOperator `json:"operator"`
	Values   []string                  `json:"values,omitempty"`
}

// A namespace selector operator is the set of operators that can be used in a selector requirement.
type NamespaceSelectorOperator string

const (
	NamespaceSelectorOpIn    NamespaceSelectorOperator = "In"
	NamespaceSelectorOpNotIn NamespaceSelectorOperator = "NotIn"
)

func (in *NamespaceSelector) DeepCopyInto(out *NamespaceSelector) {
	*out = *in
	if in.Values != nil {
		in, out := &in.Values, &out.Values
		*out = make([]string, len(*in))
		copy(*out, *in)
	}
}

func (in *NamespaceSelector) DeepCopy() *NamespaceSelector {
	if in == nil {
		return nil
	}
	out := new(NamespaceSelector)
	in.DeepCopyInto(out)
	return out
}

//NamespaceSelector selector namespace
func (in *NamespaceSelector) CheckSelector(ns string) bool {
	switch in.Operator {
	//if namespace in values,then return true
	case NamespaceSelectorOpIn:
		for _, val := range in.Values {
			if ns == val {
				return true
			}
		}
		return false
	//
	case NamespaceSelectorOpNotIn:
		for _, val := range in.Values {
			if ns == val {
				return false
			}
		}
		return true
	default:
		fmt.Println("NamespaceSelector Operator", in.Operator, "is invalid")
	}

	return false
}

// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *AdmissionWebhook) DeepCopyInto(out *AdmissionWebhook) {
	*out = *in
	if in.ClientConfig != nil {
		in, out := &in.ClientConfig, &out.ClientConfig
		*out = new(WebhookClientConfig)
		**out = **in
	}
	if in.WebhookServers != nil {
		in, out := &in.WebhookServers, &out.WebhookServers
		*out = make([]string, len(*in))
		copy(*out, *in)
	}
	if in.NamespaceSelector != nil {
		in, out := &in.NamespaceSelector, &out.NamespaceSelector
		*out = new(NamespaceSelector)
		(*in).DeepCopyInto(*out)
	}
	return
}

// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdmissionWebhook.
func (in *AdmissionWebhook) DeepCopy() *AdmissionWebhook {
	if in == nil {
		return nil
	}
	out := new(AdmissionWebhook)
	in.DeepCopyInto(out)
	return out
}

type AdmissionOperation string

const (
	AdmissionOperationCreate  = "Create"
	AdmissionOperationUpdate  = "Update"
	AdmissionOperationUnknown = "unknown"
)

type AdmissionResourcesKind string

const (
	AdmissionResourcesApplication = "application"
	AdmissionResourcesDeployment  = "deployment"
)

type WebhookFailurePolicyKind string

const (
	WebhookFailurePolicyIgnore = "Ignore"
	WebhookFailurePolicyFail   = "Fail"
)

type WebhookClientConfig struct {
	//url
	Url string `json:"url"`
	//pem encoded ca cert that signs the server cert used by the webhook
	CaBundle string `json:"caBundle"`
	//webhook service namespace
	Namespace string `json:"namespace"`
	//webhook service name
	Name string `json:"name"`
	//url path
	Path string `json:"path"`
	//port
	Port int `json:"port"`
}
